package gates;

import java.awt.Graphics;

import master.*;

/**
 * 
 * A functional representation of the Hadamard gate, made so it can act on any size register, and any bit
 * 
 * @author Matthew
 *
 */
public class Hadamard extends QuantumGate {


	private static IllegalArgumentException
	bitException = new IllegalArgumentException("The register is not big enough to work on that bit");

	private int bit;
	private int dim;
	private int check;
	ComplexNumber[] a;


	public Hadamard(int bit){


		this.check = bit;
		this.bit = (int) Math.pow(2, bit);
		


	}



	//method to act the gate on the register
	public void actOnReg (QuantumRegister register){

		//Catch errors caught by the target bit not being in the register


		if (check < 0 ||check >= register.getQBitLength() ){
			throw bitException; 

		}
		dim = (int)Math.pow(2, register.getQBitLength());

		a = new ComplexNumber[dim];
		
		
		//create a temporary array
		float temp = (float) (1 / Math.sqrt(2));

		for (int i = 0; i < dim; i ++){
			a[i] = new ComplexNumber();
		}


		for(int i=0; i < dim; i ++){


			/**
			 *
			 *create a temporary variable, storing the value of the current element of the register
			 *example, register in state |1>, = (0,1), this changes it to (0,-1)
			 *and creates temporary vector (1,0) 
			 * 
			 */

			if (register.getCoefficient(i).getReal() != new ComplexNumber().getReal()){


				ComplexNumber complexTemp = new ComplexNumber(register.getCoefficient(i).getReal(), register.getCoefficient(i).getImaginary()); 
				a[i^bit] = complexTemp;

				//if the qubit is a 1, set it to -ve 1, otherwise leave it
				if (i > (i^bit)){
					ComplexNumber z = register.getCoefficient(i).multByNo(-1);
					register.setCoefficient(z, i);
				}

			}
		}

		/**
		 *make the register the sum of its current value, plus the temporary array
		 *created to hold the "other" bit made by the hadamard bit, continuing the example above
		 *this part of code adds the register and the temporary array together, giving (1,-1) and then
		 *multiplies by 1/sqrt(2), giving H |1 > = 1/sqrt(2) (|0> - |1>)
		 * 
		 */		
		for (int j =0; j < dim; j++){
			ComplexNumber temp1 = register.getCoefficient(j).add(a[j]); 
			temp1 = temp1.multByNo(temp);
			register.setCoefficient(temp1, j);		
		}



	}






	public boolean checkDim(QuantumRegister register){
		//checks dimensions of quantum register and compares with dimensions of matrix
		if (register.getDimension() == dim){
			return true;
		}else{
			return false;
		}


	}




	public void draw(Graphics g, int x, int y, float scale) {
        g.drawRect(x, y+(int)(scale*Math.log(bit)/Math.log(2)), (int)(scale), (int)(scale));
	}
	
	



	@Override
	public int[] getActingBits() {
		int bits[] = {check};
		return bits;
	}




}
